package com.example.hszpad.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.example.hszpad.SlaveActivity;
import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.data.DataHolder;
import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters;
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.slave.ModbusSlave;
import com.intelligt.modbus.jlibmodbus.slave.ModbusSlaveFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

/**
 * modbus SlaveService
 */
public class ModbusSlaveService extends Service {
    public static final String BROADCAST_ONWRITETOSINGLECOIL = "com.example.hszpad.onWriteToSingleCoil";
    public static final String BROADCAST_ONWRITETOMULTIPLECOILS = "com.example.hszpad.onWriteToMultipleCoils";
    public static final String BROADCAST_ONWRITETOSINGLEHOLDINGREGISTER = "com.example.hszpad.onWriteToSingleHoldingRegister";
    public static final String BROADCAST_ONWRITETOMULTIPLEHOLDINGREGISTERS = "com.example.hszpad.onWriteToMultipleHoldingRegisters";

    public static final String TAG = "ModbusSlaveService";

    public final ModbusHoldingRegisters hr = new ModbusHoldingRegisters(100);
    public ModbusSlave slave;
    private LocalBinder localBinder = new LocalBinder();
    private LocalBroadcastManager localBroadcastManager;

    private onReceiveListener onReceiveListener;

    public void setOnReceiveListener(ModbusSlaveService.onReceiveListener onReceiveListener) {
        this.onReceiveListener = onReceiveListener;
    }

    public ModbusSlaveService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind:");
        return localBinder;
    }

    public class LocalBinder extends Binder {


        public ModbusSlaveService getServices() {
            return ModbusSlaveService.this;
        }

    }

    public void start() {
        Log.e(TAG, "启动salve:");
        new Thread() {

            @Override
            public void run() {
                try {
                    // 设置主机TCP参数
                    TcpParameters tcpParameters = new TcpParameters();

                    // 设置TCP的ip地址
                    InetAddress adress = null;
                    try {
                        adress = InetAddress.getByName("127.0.0.1");
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }

                    // TCP参数设置ip地址
                    // tcpParameters.setHost(InetAddress.getLocalHost());
                    tcpParameters.setHost(adress);

                    // TCP设置长连接
                    tcpParameters.setKeepAlive(true);
                    // TCP设置端口，这里设置是默认端口502
                    tcpParameters.setPort(8080);
                    slave = ModbusSlaveFactory.createModbusSlaveTCP(tcpParameters);
                    Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG);
                    MyOwnDataHolder dh = new MyOwnDataHolder();
                    dh.addEventListener(new SlaveActivity.ModbusEventListener() {
                        @Override
                        public void onWriteToSingleCoil(int address, boolean value) {
                            System.out.print("onWriteToSingleCoil: address " + address + ", value " + value);
//                            Intent intent = new Intent(BROADCAST_ONWRITETOSINGLECOIL);
//                            intent.putExtra("address", address);
//                            intent.putExtra("value", value);
//                            localBroadcastManager.sendBroadcast(intent);
                        }

                        @Override
                        public void onWriteToMultipleCoils(int address, int quantity, boolean[] values) {
                            System.out.print("onWriteToMultipleCoils: address " + address + ", quantity " + quantity);
//                            Intent intent = new Intent(BROADCAST_ONWRITETOMULTIPLECOILS);
//                            intent.putExtra("address", address);
//                            intent.putExtra("values", values);
//                            localBroadcastManager.sendBroadcast(intent);
                        }

                        @Override
                        public void onWriteToSingleHoldingRegister(int address, int value) {
                            System.out.print("onWriteToSingleHoldingRegister: address " + address + ", value " + value);
//                            Intent intent = new Intent(BROADCAST_ONWRITETOSINGLEHOLDINGREGISTER);
//                            intent.putExtra("address", address);
//                            intent.putExtra("value", value);
//                            localBroadcastManager.sendBroadcast(intent);
                            ModbusSlaveService.this.onWriteToSingleHoldingRegister(address, value);
                        }

                        @Override
                        public void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values) {
                            System.out.print("onWriteToMultipleHoldingRegisters: address " + address + ", quantity " + quantity);
//                            Intent intent = new Intent(BROADCAST_ONWRITETOMULTIPLEHOLDINGREGISTERS);
//                            intent.putExtra("address", address);
//                            intent.putExtra("quantity", quantity);
//                            intent.putExtra("values", values);
//                            localBroadcastManager.sendBroadcast(intent);
                            ModbusSlaveService.this.onWriteToMultipleHoldingRegister(address, quantity, values);
                        }
                    });

                    slave.setDataHolder(dh);
                    slave.getDataHolder().setHoldingRegisters(hr);
                    slave.setServerAddress(1);
                    /*
                     * using master-branch it should be #slave.open();
                     */
                    slave.listen();

                    /*
                     * since 1.2.8
                     */
//                    if (slave.isListening()) {
//                        Runtime.getRuntime().addShutdownHook(new Thread() {
//                            @Override
//                            public void run() {
//                                synchronized (slave) {
//                                    slave.notifyAll();
//                                }
//                            }
//                        });
//
//                        synchronized (slave) {
//                            slave.wait();
//                        }
//
//                        /*
//                         * using master-branch it should be #slave.close();
//                         */
//                        slave.shutdown();
//                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void stop() {
        if (slave != null) {
            try {
                Log.e(TAG, "关闭salve:");
                slave.shutdown();
            } catch (ModbusIOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate:");
        localBroadcastManager = LocalBroadcastManager.getInstance(this);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
//
        Log.e(TAG, "onStartCommand:");
        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy:");
        super.onDestroy();
    }

    public String myway() {
        Log.e(TAG, "myway:hello world");
        return "hello world";
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind:");
        return super.onUnbind(intent);
    }

    public static class MyOwnDataHolder extends DataHolder {

        final List<SlaveActivity.ModbusEventListener> modbusEventListenerList = new ArrayList<SlaveActivity.ModbusEventListener>();

        public MyOwnDataHolder() {
            // you can place the initialization code here
            /*
             * something like that: setHoldingRegisters(new SimpleHoldingRegisters(10));
             * setCoils(new Coils(128)); ... etc.
             */
        }

        public void addEventListener(SlaveActivity.ModbusEventListener listener) {
            modbusEventListenerList.add(listener);
        }

        public boolean removeEventListener(SlaveActivity.ModbusEventListener listener) {
            return modbusEventListenerList.remove(listener);
        }

        @Override
        public void writeHoldingRegister(int offset, int value)
                throws IllegalDataAddressException, IllegalDataValueException {
            for (SlaveActivity.ModbusEventListener l : modbusEventListenerList) {
                l.onWriteToSingleHoldingRegister(offset, value);
            }
            super.writeHoldingRegister(offset, value);
        }

        @Override
        public void writeHoldingRegisterRange(int offset, int[] range)
                throws IllegalDataAddressException, IllegalDataValueException {
            for (SlaveActivity.ModbusEventListener l : modbusEventListenerList) {
                l.onWriteToMultipleHoldingRegisters(offset, range.length, range);
            }
            super.writeHoldingRegisterRange(offset, range);
        }

        @Override
        public void writeCoil(int offset, boolean value) throws IllegalDataAddressException, IllegalDataValueException {
            for (SlaveActivity.ModbusEventListener l : modbusEventListenerList) {
                l.onWriteToSingleCoil(offset, value);
            }
            super.writeCoil(offset, value);
        }

        @Override
        public void writeCoilRange(int offset, boolean[] range)
                throws IllegalDataAddressException, IllegalDataValueException {
            for (SlaveActivity.ModbusEventListener l : modbusEventListenerList) {
                l.onWriteToMultipleCoils(offset, range.length, range);
            }
            super.writeCoilRange(offset, range);
        }
    }

    public void setValue(int address, int value) {
        try {
            hr.set(address, value);
        } catch (IllegalDataAddressException e) {
            e.printStackTrace();
        } catch (IllegalDataValueException e) {
            e.printStackTrace();
        }
    }

    public void onWriteToSingleHoldingRegister(int address, int value) {
        if (onReceiveListener != null) {
            onReceiveListener.onRecevie(address, value);
        }
    }

    public void onWriteToMultipleHoldingRegister(int address, int quantity, int[] values) {
        if (onReceiveListener != null) {
            onReceiveListener.onReceiveMultiple(address, quantity, values);
        }
    }

    public interface onReceiveListener {
        void onRecevie(int address, int value);

        void onReceiveMultiple(int address, int quantity, int[] values);
    }
}
